home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / ust1a.arc / SARCH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-09-05  |  12.4 KB  |  534 lines

  1. /*+
  2.  * File: SARCH
  3.  * Description:
  4.  *      This is a simple archive utility program.
  5.  *      Sarch tries to only rely on the C stdio library functions.
  6.  *      When transferring multiple files between two machines that only have a
  7.  *      single file transfer utility, sarch becomes handy. Multiple files
  8.  *      are converted to a sinle file on one end, transfered to the other 
  9.  *      machine and extracted to the original files at the destination.
  10.  *      System dependent features are very few, keeping it simple
  11.  *      and portable. Efficiency is sacrificed for portability.
  12.  *        CRCs are computed when updateing and when extracting.
  13.  *  
  14.  * Usage:
  15.  *  sarch -{m,u,x,a,t} archname file1 .. filen
  16.  *      -m      Print file names within the archive.
  17.  *      -u      Add or update files to the archive.
  18.  *      -x      Extract files from archive.
  19.  *      -a      Extract all files from the rachive.
  20.  *      -t      PCDOS related. When extracting, test mode is set.
  21.  *
  22.  *
  23.  *  Author: Mohsen Banan.
  24.  *
  25.  *  This program is public domain software, no warranty intended or
  26.  *  implied.
  27.  *  General permission to copy or modify, but not for profit,  is
  28.  *  hereby  granted.
  29.  *
  30.  *
  31.  * Functions:
  32.  *
  33.  *  Sarch relies on the archive manipulating functions:
  34.  *      ar_open(), ar_close()
  35.  *      ar_get(), ar_put(), ar_seek().
  36.  *      ar_get, gets (extracts) a file from the archive.
  37.  *      ar_put, puts (adds) a file to the archive.
  38.  *
  39.  *
  40.  * Audit Trail:  $Log:    sarch.c,v $
  41.  * Revision 1.1  85/08/28  08:38:52  mohsen
  42.  * original posting to the net
  43.  * 
  44.  * Revision 1.1  85/08/13  17:30:27  mohsen
  45.  * Initial revision
  46.  * 
  47.  * Revision 1.2  85/04/25  10:27:22  mohsen
  48.  * In this version sarch was working fine with the -a and -u options.
  49.  * 
  50.  * Revision 1.1  85/04/19  16:24:43  mohsen
  51.  * Initial revision
  52.  * 
  53.  *
  54. -*/
  55.  
  56. #ifdef RCS_VER
  57. static char *rcs = "$Header: sarch.c,v 1.1 85/08/28 08:38:52 mohsen Exp $";
  58. #endif
  59.  
  60. /* #includes */
  61. #include "mbstd.h"
  62. #include <stdio.h>
  63. #include <fcntl.h>
  64. #ifdef unix
  65. #include "msc3.h"
  66. #endif
  67.  
  68. /* #defines */
  69. #define AR_BSTR     "<archive>"
  70. #define AR_ESTR     "<archive>"
  71.  
  72. /*
  73.  * All fileds of ARCH_HDR are strings (0 terminated),
  74.  * All fields are left justified.
  75.  */
  76. typedef struct {
  77.     CHAR ar_bstr[16];       /* begining archive string */
  78.     CHAR fname[16];
  79.     CHAR fsize[8];
  80.     CHAR fcrc[8];
  81.     CHAR ar_estr[16];       /* end archive string */
  82. } ARCH_HDR;
  83.  
  84. /* external variables */
  85.  
  86. /* referenced external function declarations */
  87. EXTERN USHORT fcrc16();
  88.  
  89. /* internal function declarations */
  90. PUBLIC VOID sarch();
  91. PUBLIC FILE * ar_open();
  92. PUBLIC INT ar_close();
  93. PUBLIC SUCC_FAIL ar_put();
  94. PUBLIC SUCC_FAIL ar_get();
  95. PUBLIC SUCC_FAIL ar_seek();
  96. LOCAL VOID wr_hdr();
  97. LOCAL SUCC_FAIL rd_hdr();
  98. LOCAL VOID fld2str();
  99. PUBLIC VOID cpf();
  100. PUBLIC VOID cant_open();
  101. STATIC VOID usage();
  102.  
  103. /* global variables */
  104.  
  105. /* static variables */
  106. STATIC CHAR * prog_name;
  107. STATIC ARCH_HDR gw_hdr;         /* generic write archive header */
  108. STATIC ARCH_HDR gr_hdr;         /* generic read archive header */
  109. STATIC BOOL txt_mode_flag;
  110.  
  111. INT
  112. main (argc, argv)
  113. INT argc;
  114. CHAR * argv[];
  115. {
  116.     sarch(argc, argv);
  117. }
  118.     
  119.  
  120. /*<
  121.  * Function:SARCH
  122.  * Description:
  123.  *  Parses the command line and relies on archive manipulating functions to do
  124.  *  what it should do.
  125.  *
  126.  * Returns:
  127.  *  VOID
  128.  * 
  129. >*/
  130. PUBLIC VOID 
  131. sarch (argc,argv)
  132. INT argc;
  133. CHAR * argv[];
  134. {
  135.     FILE * ar_fp;
  136.  
  137.     BOOL    add_flag;
  138.     BOOL    xt_flag;
  139.     BOOL    xt_all_flag;
  140.  
  141.     INT i;
  142.  
  143.     add_flag = xt_flag = xt_all_flag = txt_mode_flag = FALSE;
  144.     ar_fp = stdout;
  145.     prog_name = argv[0];
  146.  
  147.     sprintf (gw_hdr.ar_bstr, "%-15s", AR_BSTR);
  148.     sprintf (gw_hdr.ar_estr, "%-15s", AR_ESTR);
  149.  
  150.     for (i=1; i<argc; ++i) {
  151.         if (*argv[i] == '-') {
  152.             /* To handle concatenated switches */
  153.             INT j;
  154.             j=i;
  155.             while (*(++argv[j])) {
  156.                 switch (*argv[j]) {
  157.                 case 'u':
  158.                 case 'U':
  159.                     /*
  160.                      * add or update a file to the archive
  161.                      */
  162.                     if (!(ar_fp = ar_open (argv[++i], "w"))) {
  163.                         cant_open(prog_name, argv[i]);
  164.                         exit (1);
  165.                     }
  166.                     add_flag = TRUE;
  167.                     break;
  168.                 case 'x':
  169.                 case 'X':
  170.                     /*
  171.                      * Extract a file from the archive.
  172.                      */
  173.                     if (!(ar_fp = ar_open (argv[++i], "r"))) {
  174.                         cant_open(prog_name,argv[i]);
  175.                         exit(1);
  176.                     }
  177.                     xt_flag = TRUE;
  178.                     break;
  179.                 case 'a':
  180.                 case 'A':
  181.                     /*
  182.                      * Extract all files with in this archive
  183.                      */
  184.                     if (!(ar_fp = ar_open (argv[i+1], "r"))) {
  185.                         cant_open(prog_name,argv[i]);
  186.                         exit(1);
  187.                     }
  188.                     xt_all_flag = TRUE;
  189.                     break;
  190.                 case 't':
  191.                 case 'T':
  192.                     txt_mode_flag = TRUE;
  193.                     break;
  194.                 default:
  195.                     usage();
  196.                     exit(1);
  197.                 } /* switch (*argv[j]) */
  198.             } /* while (*(++argv[j])) */
  199.         } /* if '-' */
  200.         else if (ar_fp == stdout) {
  201.             /* 
  202.              * This is equivalent to "-u" option, ar_fp is stdout.
  203.              */
  204.              add_flag = TRUE;
  205.         }
  206.         else {
  207.             /*
  208.              * the rest of command line arguments are assumed to be file names.
  209.              */
  210.             if (add_flag) {
  211.                 ar_put (ar_fp, &gw_hdr,argv[i]);
  212.             }
  213.             else if (xt_flag) {
  214.                 ar_seek (ar_fp, &gr_hdr, argv[i]);
  215.                 ar_get (ar_fp,&gr_hdr);
  216.             }
  217.             else if (xt_all_flag) {
  218.                 while ( ar_seek (ar_fp, &gr_hdr,(CHAR *) NULL) == SUCCESS ) {
  219.                     ar_get (ar_fp, &gr_hdr);
  220.                 }
  221.             }
  222.             else {
  223.                 /*
  224.                 OOPS();
  225.                 */
  226.             }
  227.         }
  228.     } /* for i<argc */
  229.     ar_close (ar_fp);
  230.     exit (0);
  231. }
  232.  
  233.  
  234. /*<
  235.  * Function:ar_open
  236.  * Description:
  237.  *  Opens an archive directory.
  238.  *
  239.  * Returns:
  240.  *  Same as fopen.
  241.  *
  242.  * 
  243. >*/
  244. PUBLIC FILE *
  245. ar_open(path, type)
  246. CHAR * path;
  247. CHAR * type;
  248. {
  249.     FILE * fp;
  250.     if ( fp=fopen(path,type) ) {
  251.         setmode (fileno(fp), O_BINARY);
  252.     }
  253.     return (fp);
  254. }
  255.  
  256.  
  257.  
  258. /*<
  259.  * Function:ar_close
  260.  * Description:
  261.  *  Closes an archive file
  262.  *
  263.  * Returns:
  264.  *  same as fclose.
  265.  * 
  266. >*/
  267. PUBLIC INT
  268. ar_close(ar_fp)
  269. FILE * ar_fp;
  270. {
  271.     return (fclose(ar_fp));
  272. }
  273.  
  274.  
  275.  
  276. /*<
  277.  * Function: ar_put
  278.  * Description:
  279.  *  Puts the contents of the file specified in "path" into the archive.
  280.  *  Archive header is written prior to copying the file.
  281.  *
  282.  * Returns:
  283.  *  SUCCESS:    
  284.  *      No problems.
  285.  *  FAIL:
  286.  *      Couldn't open the file that it is supposed to put it in.
  287.  * 
  288. >*/
  289. PUBLIC SUCC_FAIL
  290. ar_put(ar_fp, p_ar_hdr, path)
  291. FILE * ar_fp;
  292. ARCH_HDR * p_ar_hdr;
  293. CHAR * path;
  294. {
  295.     FILE * fp;
  296.     SUCC_FAIL retval;
  297.     LONG fsize;
  298.     USHORT crc;
  299.  
  300.     retval = SUCCESS;
  301.     if (!(fp = fopen(path, "r"))) {
  302.         cant_open (prog_name, path);
  303.         retval = FAIL;
  304.     } else {
  305.         setmode (fileno(fp), O_BINARY);
  306.         crc = fcrc16(fp, (USHORT)0, &fsize);
  307.         rewind(fp);
  308.         sprintf (p_ar_hdr->fsize, "%-7ld", fsize);
  309.         sprintf (p_ar_hdr->fcrc, "%-7x", (int)crc);
  310.         sprintf (p_ar_hdr->fname, "%-15s", path);
  311.         wr_hdr(ar_fp, p_ar_hdr);
  312.         cpf (fp, ar_fp, fsize);
  313.         fclose(fp);
  314.     }
  315.     return (retval);
  316. }
  317.  
  318.  
  319. /*<
  320.  * Function:ar_get
  321.  * Description:
  322.  *  Gets (extracts) the contents of a file from the archive.
  323.  *  and stores it in the file specified in the archive header.
  324.  *  ar_get is to be invoked after the execution of ar_seek.
  325.  *
  326.  * Returns:
  327.  *  SUCCESS:
  328.  *      Every thing went fine.
  329.  *  FAIL:
  330.  *      Couldn't open the file.
  331.  *
  332.  * 
  333. >*/
  334. PUBLIC SUCC_FAIL
  335. ar_get(ar_fp, p_ar_hdr)
  336. FILE  * ar_fp;
  337. ARCH_HDR * p_ar_hdr;
  338. {
  339.     FILE * fp;
  340.     SUCC_FAIL retval;
  341.     LONG fsize;
  342.     LONG nfsize;
  343.     USHORT crc;
  344.     USHORT ncrc;
  345.     UINT   int_crc;
  346.  
  347.     retval = SUCCESS;
  348.  
  349.     if (!(fp = fopen(p_ar_hdr->fname, "w+"))) {
  350.         cant_open (prog_name, p_ar_hdr->fname);
  351.         retval = FAIL;
  352.     } else {
  353.         setmode(fileno(fp), O_BINARY);
  354.         sscanf (p_ar_hdr->fsize, "%ld", &fsize);
  355.         cpf((FILE *)ar_fp, fp, fsize);
  356.         rewind(fp);
  357.         ncrc = fcrc16(fp, (USHORT)0, &nfsize);
  358.         sscanf (p_ar_hdr->fcrc, "%x", &int_crc);
  359.         crc = int_crc;
  360.         if ( (crc != ncrc) || (fsize != nfsize) ) {
  361.             retval = FAIL;
  362.             fprintf(stderr, "%s: Problem extacting %s size=%ld, crc=%x\n",
  363.                     prog_name, p_ar_hdr->fname, fsize, (int)crc);
  364.             fprintf(stderr, "%s: Problem extacting %s nsize=%ld, ncrc=%x\n",
  365.                     prog_name, p_ar_hdr->fname, nfsize, (int)ncrc);
  366.         }
  367.         fclose(fp);
  368.     }
  369.     return (retval);
  370. }
  371.  
  372.  
  373. /*<
  374.  * Function: ar_seek
  375.  * Description:
  376.  *  If path is NULL, the current archive header is read into
  377.  *  p_ar_hdr.
  378.  *  Otherwise, the archive is searched for the specified file
  379.  *  name addressed by path.
  380.  *
  381.  * Returns:
  382.  *  SUCCESS if found.
  383.  *  FAIL    if not found, or problem.
  384.  *
  385.  * 
  386. >*/
  387. LOCAL SUCC_FAIL
  388. ar_seek(ar_fp, p_ar_hdr, path) 
  389. FILE * ar_fp;
  390. ARCH_HDR * p_ar_hdr;
  391. CHAR * path;
  392. {
  393.     SUCC_FAIL retval;
  394.  
  395.     retval = SUCCESS;
  396.     if (!path ) {
  397.         /* then get it any way */
  398.         retval = rd_hdr(ar_fp, p_ar_hdr);
  399.     } else {
  400.         
  401.     }
  402.     return (retval);
  403. }
  404.  
  405.  
  406. /*<
  407.  * Function:wr_hdr
  408.  * Description:
  409.  *  Copy the contents of ARCH_HDR to the archive header.
  410.  *  See rd_hdr for the file archive header picture.
  411.  *
  412.  * Returns:
  413.  *  VOID
  414.  * 
  415. >*/
  416. LOCAL VOID
  417. wr_hdr (ar_fp, p_ar_hdr)
  418. FILE * ar_fp;
  419. ARCH_HDR * p_ar_hdr;
  420. {
  421.     fprintf (ar_fp , "%-15s", p_ar_hdr->ar_bstr);
  422.     fprintf (ar_fp , "%-15s", p_ar_hdr->fname);
  423.     fprintf (ar_fp , "%-7s", p_ar_hdr->fsize);
  424.     fprintf (ar_fp , "%-7s", p_ar_hdr->fcrc);
  425.     fprintf (ar_fp , "%-15s", p_ar_hdr->ar_estr);
  426.     putc ('\n',ar_fp);
  427. }
  428.  
  429.  
  430. /*<
  431.  * Function:rd_hdr
  432.  * Description:
  433.  *  Reads a header and fills up the ARCH_HDR.
  434.  *
  435. 0         1         2         3         4         5         6   
  436. 0123456789012345678901234567890123456789012345678901234567890
  437. 123456789012345678901234567890123456789012345678901234567890
  438. b              b              b      b     b
  439.     ar_bstr        fname        fsize  fcrc     ar_estr
  440.  *
  441.  * Returns:
  442.  *  SUCCESS:
  443.  *  FAIL:
  444.  *      archive header is bad.
  445.  *
  446.  * 
  447. >*/
  448. LOCAL SUCC_FAIL
  449. rd_hdr (ar_fp, p_ar_hdr)
  450. FILE * ar_fp;
  451. ARCH_HDR * p_ar_hdr;
  452. {
  453.     SUCC_FAIL   retval;
  454.     CHAR    hdr_line[256];
  455.     INT i;
  456.  
  457.     retval = SUCCESS;
  458.     if (!fgets (hdr_line, 255,ar_fp)) {
  459.         retval = FAIL;
  460.     } else {
  461.         fld2str (&hdr_line[0], p_ar_hdr->ar_bstr, 15);
  462.  
  463.         for (i=15; i<30; ++i) {
  464.             if ( hdr_line[i] != ' ') {  
  465.                 p_ar_hdr->fname[i-15] = hdr_line[i];
  466.             } else {
  467.                 break;
  468.             }
  469.         }
  470.         p_ar_hdr->fname[i-15] = '\0';
  471.                 
  472.         fld2str (&hdr_line[30], p_ar_hdr->fsize, 7);
  473.         fld2str (&hdr_line[37], p_ar_hdr->fcrc, 7);
  474.         fld2str (&hdr_line[43], p_ar_hdr->ar_estr, 15);
  475.     }
  476.     return (retval);
  477.  
  478. }
  479.  
  480. LOCAL VOID
  481. fld2str ( fld, str, size)
  482. CHAR * fld;
  483. CHAR * str;
  484. INT size;
  485. {
  486.     INT i;
  487.     for (i=0; i<size; ++i) {
  488.         *str++ = *fld++;
  489.     }
  490.     *str = '\0';
  491. }
  492.  
  493.     
  494.  
  495. /*<
  496.  * Function:cpf
  497.  * Description:
  498.  *  Copy the first <fsize> bytes of <src_fp> to <dst_fp>
  499.  *
  500.  * Returns:
  501.  *    VOID
  502.  *
  503.  * Side Effects:
  504.  *    Both src_fp and dst_fp characters pointers are moved.
  505.  *
  506. >*/
  507. LOCAL VOID
  508. cpf (src_fp, dst_fp, fsize)
  509. FILE * src_fp;
  510. FILE * dst_fp;
  511. LONG fsize;
  512. {
  513.     LONG i;
  514.     for (i=0; i<fsize; ++i) {
  515.         putc(getc(src_fp), dst_fp);
  516.     }
  517. }
  518.  
  519.  
  520. PUBLIC VOID
  521. cant_open (prog_name,filename)
  522. CHAR * prog_name;
  523. CHAR * filename;
  524. {
  525.     fprintf (stderr, "%s :can not open %s \n", prog_name, filename);
  526.  
  527. STATIC VOID
  528. usage ()
  529. {
  530.     fprintf (stderr, "Usage: %s [-u] [-x] <filename> \n", prog_name);
  531. }
  532.  
  533.